added Feb 2001 SDK
[windows-sources.git] / shared source / vb / language / shared / norlsallocator.h
blob4bd984b134a45bf04bd2e87bc50f7b0e28d1ab2f
1 //-------------------------------------------------------------------------------------------------
2 //
3 // Copyright (c) Microsoft Corporation. All rights reserved.
4 //
5 // Implements No Release Allocator.
6 //
7 //-------------------------------------------------------------------------------------------------
9 #pragma once
12 //to track nrlsalloc locations, #define NRLSTRACK
13 // set NRLSTRACK_GETSTACKS to 1 to track NRLSAllocations and the call stacks. Uses lots of mem: very expensive
15 //#define NRLSTRACK DEBUG && !defined( VBDBGEE ) && !defined(NDEBUG) && !defined(BUILDING_VBC) && !defined(BUILDING_VB7TO8)
16 //#define NRLSTRACK_GETSTACKS NRLSTRACK
18 #if NRLSTRACK
20 // we're tracking allocations.
22 #include <hash_set>
23 using namespace stdext;
25 // we're tracking allocations.
27 struct VBMemoryInUse
29 long nHeapTotalBytes;
30 long nHeapTotalAllocs;
32 long nNrlsTotalBytes;
33 long nNrlsTotalAllocs;
37 class NrlsAllocTracker
39 public:
40 NrlsAllocTracker():
41 g_nSerialNo(0)
44 ~NrlsAllocTracker()
47 long AddAllocator(NorlsAllocator *pAllocator);
49 void RemoveAllocator(NorlsAllocator *pAllocator);
51 CComBSTR GetAllocatorStatusReport(_Out_ long *pnCnt, _Out_ long *pnTotMem);
52 VBMemoryInUse & GetVBMemoryStats(_In_ LPCSTR strDesc);
55 private:
56 typedef std::list<NorlsAllocator *> listNorls;
57 listNorls m_set;
58 CTinyLock m_lock;
59 long g_nSerialNo;
60 VBMemoryInUse m_VBMemoryInUse ;
64 extern NrlsAllocTracker *g_NrlsAllocTracker;
65 #if NRLSTRACK_GETSTACKS
66 typedef struct {
67 void * m_ptrNextBlock; // linked list of allocations: point to prior one
68 size_t m_size; // size of the nrls data
69 void * m_data; // ptr to the actual NRLS data
70 } NrlsHeapData;
71 #endif NRLSTRACK_GETSTACKS
73 #endif NRLSTRACK
77 // Holds a page of memory being used by the NorlsAllocator.
78 struct NorlsPage
80 #if DEBUG
81 size_t sentinalStart;
82 #endif
84 NorlsPage * next; // next page in use.
85 BYTE * firstAvail; // first available byte for allocation.
86 BYTE * limitAvail; // limit for allocation.
88 #if DEBUG
89 size_t sentinalEnd; // Buffer overflow check
90 #endif
93 class NorlsMark
95 private:
96 friend class NorlsAllocator;
98 NorlsPage * page; // page.
99 BYTE * nextFree; // first free location within the page.
100 unsigned depth;
102 #if NRLSTRACK
103 long m_nTotalAllocatedAtMark;
104 #if NRLSTRACK_GETSTACKS
105 NrlsHeapData * m_pLastBlockAtMark; // ptr to linked list of alloc'd Heap blocks so VSAssert CHeapSpy can watch Nrlsallocs
106 #endif NRLSTRACK_GETSTACKS
107 #endif //NRLSTRACK
112 #if NRLSTRACK
113 #define NORLSLOC __WFILE__, __LINE__
114 #else
115 #define NORLSLOC -1
116 #endif
118 class NorlsAllocator
120 friend class NrlsAllocTracker;
121 public:
122 NEW_CTOR_SAFE()
124 class AllowingWrite
126 private:
127 NorlsAllocator * heap;
128 bool alreadyInAllowingWrite;
129 public:
130 AllowingWrite(NorlsAllocator * heap)
132 this->heap = heap;
133 if (heap)
135 alreadyInAllowingWrite = heap->inAllowingWrite;
136 heap->inAllowingWrite = true;
138 else
140 alreadyInAllowingWrite = false;
143 ~AllowingWrite()
145 if (!alreadyInAllowingWrite && heap)
147 heap->inAllowingWrite = false;
150 bool OwnsHeapWriteability()
152 return !alreadyInAllowingWrite;
158 NorlsAllocator(
159 #if NRLSTRACK
160 _In_ WCHAR *szFile, _In_ long nLineNo
161 #else
162 _In_ int nUnused
163 #endif NRLSTRACK
165 ~NorlsAllocator();
167 NorlsAllocator(
168 #if NRLSTRACK
169 _In_ WCHAR *szFile, _In_ long nLineNo,
170 #else
171 _In_ int nUnused,
172 #endif NRLSTRACK
173 _In_ PageHeap& heapToAllocateFrom
176 PageHeap& GetPageHeap()
178 return m_heapPage;
181 void ForbidWrite(void * p, size_t sz)
183 VerifyHeapEntity();
184 ForbidWriteInternal(p, sz);
186 void AllowWrite(void * p, size_t sz)
188 VerifyHeapEntity();
189 AllowWriteInternal(p, sz);
192 void DisallowReadOnlyDirectives()
194 VerifyHeapEntity();
195 DisallowReadOnlyDirectivesInternal();
197 void AllowReadOnlyDirectives()
199 VerifyHeapEntity();
200 AllowReadOnlyDirectivesInternal();
202 bool AllowingReadOnlyDirectives()
204 VerifyHeapEntity();
205 return AllowingReadOnlyDirectivesInternal();
207 void MakeCurrentPageReadOnly()
209 VerifyHeapEntity();
210 MakeCurrentPageReadOnlyInternal();
211 } // Calling Alloc makes it writeable until the next call to MakeReadOnly
212 void MakeCurrentPageWriteable()
214 VerifyHeapEntity();
215 MakeCurrentPageWriteableInternal();
216 } // Calling Alloc makes it writeable until the next call to MakeReadOnly
217 void MakeAllHeapReadOnly()
219 VerifyHeapEntity();
220 MakeAllHeapReadOnlyInternal();
222 void MakeAllHeapWriteable()
224 VerifyHeapEntity();
225 MakeAllHeapWriteableInternal();
228 bool IsAddressInCurrentPage (const void * addr) const;
229 bool IsAddressInHeap (const void * addr) const
231 for (NorlsPage * page = pageList; page; page = page->next)
233 if (addr >= page && addr < page->limitAvail)
234 return true;
236 return false;
239 void* AllocNonZero(size_t sz);
240 void* Alloc(size_t sz);
241 template <typename T>
242 T* Alloc()
244 return (T*)Alloc(sizeof(T));
246 template <typename T>
247 T* _fastcall AllocArray(size_t count)
249 return (T*)Alloc(VBMath::Multiply(sizeof(T),count));
252 void *Resize(
253 _In_bytecount_(cbSizeOld) void* pv,
254 _In_ size_t cbSizeOld,
255 _In_ size_t cbSizeNew);
257 void ValidateHeap();
258 PWSTR AllocStr(PCWSTR str);
259 NorlsMark Mark();
260 void Mark(NorlsMark * mark);
261 void Free(NorlsMark * mark);
262 void FreeHeap();
263 size_t CalcCommittedSize () const;
264 const WCHAR* GetDebugIdentifier() const;
265 #if NRLSTRACK
266 WCHAR *m_szFile;
267 long m_nLineNo;
268 DWORD m_dwCreatedThreadId; // the thread on which this allocator was created
269 DWORD m_dwAllocThreadId;// the thread on which allocations are occuring
270 long m_nSerialNo; // the allocator's serialno
271 long m_nSeqNo; /// the sequence # of the allocation for this allcoator
272 ULONG m_nTotalAllocated;
273 #if NRLSTRACK_GETSTACKS
274 NrlsHeapData * m_pLastBlock; // ptr to linked list of alloc'd Heap blocks so VSAssert CHeapSpy can watch Nrlsallocs
275 HANDLE TrackingHeapToUse();
276 static HANDLE g_nraSymbolHeap ;
278 #endif NRLSTRACK_GETSTACKS
281 #endif NRLSTRACK
283 private:
284 NorlsAllocator(const NorlsAllocator&);
285 NorlsAllocator& operator=(const NorlsAllocator&);
287 void Init(ProtectedEntityFlagsEnum entity);
288 void VerifyHeapEntity()
290 VSASSERT(entity, "Heap entity must be set before manipulating heap writeability");
292 void VerifyHeap();
293 void ForbidWriteInternal(void * p, size_t sz);
294 void AllowWriteInternal(void * p, size_t sz);
296 //allocates memory but doesn't clear it.
297 //'sz' [in/out] returns the true allocation size
298 void* _AllocNonZero(size_t& sz);
300 void DisallowReadOnlyDirectivesInternal()
302 allowReadOnlyDirectives = false;
304 void AllowReadOnlyDirectivesInternal()
306 allowReadOnlyDirectives = true;
308 bool AllowingReadOnlyDirectivesInternal()
310 return allowReadOnlyDirectives;
312 void MakeCurrentPageReadOnlyInternal(); // Calling Alloc makes it writeable until the next call to MakeReadOnly
313 void MakeCurrentPageWriteableInternal(); // Calling Alloc makes it writeable until the next call to MakeReadOnly
314 void MakeAllHeapReadOnlyInternal();
315 void MakeAllHeapWriteableInternal();
317 void SetPageWriteStatus(NorlsPage * page, bool writeable);
318 void SetPageRegionWriteStatus(NorlsPage * first, NorlsPage * last, bool writeable);
319 void SetAllPagesWriteStatus(bool writeable);
321 BYTE * nextFree; // location of free area
322 BYTE * limitFree; // just beyond end of free area in this page.
324 NorlsPage * pageList; // list of pages used by this allocator.
325 NorlsPage * pageLast; // last page in the list.
327 // The source of pages for this heap.
328 PageHeap& m_heapPage;
329 unsigned m_depth;
331 void AllocNewPage(size_t sz);
332 NorlsPage * NewPage(size_t sz);
334 ProtectedEntityFlagsEnum entity;
335 bool allowReadOnlyDirectives;
336 bool anyPageMarkedReadOnly;
337 bool inAllowingWrite;
339 #ifdef DEBUG
340 inline size_t DebugSize (size_t sz) const
342 // integer overflow
343 if (!(sz < sz + 1 + sizeof(size_t) + sizeof(void*) + sizeof(void*)))
345 VSASSERT(sz < sz + 1 + sizeof(size_t) + sizeof(void*) + sizeof(void*), "Invalid");
346 return 0;
348 return VBMath::RoundUpAllocSize(sizeof(size_t)) + VBMath::RoundUpAllocSize(sz + 1); // int at beginning for size, plus 1 (or more) bytes of sentinel.
350 static const BYTE DEBUGSENTINAL = 0xAE; // put at end of block to detect overrun.
351 #endif //DEBUG
354 class NRHeapMarker
356 public:
357 NRHeapMarker(NorlsAllocator * h)
359 heap = h;
360 heap->Mark(&mark);
362 ~NRHeapMarker()
364 heap->Free(&mark);
366 private:
367 NorlsAllocator * heap;
368 NorlsMark mark;
371 class NRHeapWriteMaker
373 public:
374 NRHeapWriteMaker(NorlsAllocator * heap) : allowingWrite(heap)
376 this->heap = heap;
377 if (heap)
379 heap->MakeAllHeapWriteable();
382 ~NRHeapWriteMaker()
384 if (heap && allowingWrite.OwnsHeapWriteability())
386 heap->AllowReadOnlyDirectives();
387 heap->MakeAllHeapReadOnly();
390 private:
391 NorlsAllocator * heap;
392 NorlsAllocator::AllowingWrite allowingWrite;
395 class NRHeapWriteAllower
397 public:
398 NRHeapWriteAllower(NorlsAllocator * heap) : allowingWrite(heap)
400 this->heap = heap;
401 if (heap)
403 heap->DisallowReadOnlyDirectives();
406 ~NRHeapWriteAllower()
408 if (heap && allowingWrite.OwnsHeapWriteability())
410 heap->AllowReadOnlyDirectives();
411 heap->MakeAllHeapReadOnly();
414 private:
415 NorlsAllocator * heap;
416 NorlsAllocator::AllowingWrite allowingWrite;